#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
仓库管理器UI组件
"""

import tkinter as tk
from tkinter import ttk, messagebox
import ttkbootstrap as ttk_bs
from ttkbootstrap.constants import *
import threading
from typing import List, Dict, Callable, Optional
from utils.logger import get_logger
from core.gitee_manager import GiteeManager
from core.deepseek_ai import deepseek_ai
from gui.progress_widget import BatchProgressManager


class RepoManagerWidget(ttk.Frame):
    """仓库管理器组件"""
    
    def __init__(self, parent, **kwargs):
        super().__init__(parent, **kwargs)
        self.logger = get_logger("RepoManagerWidget")
        
        # 状态变量
        self.gitee_manager: Optional[GiteeManager] = None
        self.repositories: List[Dict] = []
        self.selected_repos: List[str] = []
        self.progress_manager = BatchProgressManager(self)
        
        self.setup_ui()
    
    def setup_ui(self):
        """设置UI界面"""
        # 主框架
        main_frame = ttk.Frame(self)
        main_frame.pack(fill=BOTH, expand=True, padx=10, pady=10)
        
        # 创建上下分栏
        main_paned = ttk.PanedWindow(main_frame, orient=tk.VERTICAL)
        main_paned.pack(fill=BOTH, expand=True)
        
        # 上半部分 - 工具栏和仓库列表
        top_frame = ttk.Frame(main_paned)
        main_paned.add(top_frame, weight=3)
        
        # 下半部分 - 进度条和日志
        bottom_frame = ttk.Frame(main_paned)
        main_paned.add(bottom_frame, weight=1)
        
        # 顶部工具栏
        self.setup_toolbar(top_frame)
        
        # 仓库列表
        self.setup_repo_list(top_frame)
        
        # 删除底部操作面板，按钮已移动到工具栏
        
        # 进度条和日志显示
        self.setup_progress_log(bottom_frame)
    
    def setup_progress_log(self, parent):
        """设置进度条和日志显示"""
        # 进度条和日志容器
        progress_log_frame = ttk_bs.LabelFrame(parent, text="操作进度和日志", bootstyle=INFO)
        progress_log_frame.pack(fill=BOTH, expand=True, pady=(10, 0))
        
        # 进度条框架
        progress_frame = ttk.Frame(progress_log_frame)
        progress_frame.pack(fill=X, padx=10, pady=5)
        
        # 进度条
        self.repo_progress_var = tk.DoubleVar()
        self.repo_progress_bar = ttk_bs.Progressbar(
            progress_frame,
            variable=self.repo_progress_var,
            maximum=100,
            bootstyle=INFO,
            length=400
        )
        self.repo_progress_bar.pack(side=LEFT, fill=X, expand=True, padx=(0, 10))
        
        # 进度百分比标签
        self.repo_progress_label = ttk.Label(progress_frame, text="0%", font=("等线", 9))
        self.repo_progress_label.pack(side=RIGHT)
        
        # 状态标签
        self.repo_status_var = tk.StringVar(value="就绪")
        self.repo_status_label = ttk.Label(progress_log_frame, textvariable=self.repo_status_var, font=("等线", 9))
        self.repo_status_label.pack(anchor=W, padx=10, pady=(0, 5))
        
        # 日志显示框架
        log_frame = ttk.Frame(progress_log_frame)
        log_frame.pack(fill=BOTH, expand=True, padx=10, pady=(0, 10))
        
        # 日志文本框
        self.repo_log_text = tk.Text(log_frame, height=6, wrap=tk.WORD, font=("等线", 9))
        repo_log_scrollbar = ttk.Scrollbar(log_frame, orient=tk.VERTICAL, command=self.repo_log_text.yview)
        self.repo_log_text.configure(yscrollcommand=repo_log_scrollbar.set)
        
        # 布局
        self.repo_log_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        repo_log_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        
        # 配置日志标签样式
        self.repo_log_text.tag_configure("INFO", foreground="blue")
        self.repo_log_text.tag_configure("SUCCESS", foreground="green")
        self.repo_log_text.tag_configure("WARNING", foreground="orange")
        self.repo_log_text.tag_configure("ERROR", foreground="red")
        self.repo_log_text.tag_configure("DEBUG", foreground="gray")
        
        # 日志操作按钮
        log_btn_frame = ttk.Frame(progress_log_frame)
        log_btn_frame.pack(fill=X, padx=10, pady=(0, 10))
        
        ttk_bs.Button(
            log_btn_frame,
            text="清空日志",
            bootstyle=SECONDARY,
            command=self._clear_repo_log,
            width=10
        ).pack(side=LEFT, padx=(0, 5))
        
        ttk_bs.Button(
            log_btn_frame,
            text="保存日志",
            bootstyle=INFO,
            command=self._save_repo_log,
            width=10
        ).pack(side=LEFT)
    
    def _append_repo_log(self, message: str, level: str = "INFO"):
        """添加仓库管理页面日志"""
        import datetime
        timestamp = datetime.datetime.now().strftime("%H:%M:%S")
        log_message = f"[{timestamp}] {message}\n"
        
        self.repo_log_text.insert(tk.END, log_message, level)
        self.repo_log_text.see(tk.END)
        
        # 限制行数（保留最后500行）
        lines = self.repo_log_text.get("1.0", tk.END).split('\n')
        if len(lines) > 500:
            self.repo_log_text.delete("1.0", f"{len(lines)-500}.0")
    
    def _clear_repo_log(self):
        """清空仓库管理页面日志"""
        self.repo_log_text.delete("1.0", tk.END)
    
    def _save_repo_log(self):
        """保存仓库管理页面日志"""
        from tkinter import filedialog
        
        filename = filedialog.asksaveasfilename(
            title="保存仓库管理操作日志",
            defaultextension=".log",
            filetypes=[("日志文件", "*.log"), ("文本文件", "*.txt"), ("所有文件", "*.*")]
        )
        
        if filename:
            try:
                with open(filename, 'w', encoding='utf-8') as f:
                    f.write(self.repo_log_text.get("1.0", tk.END))
                messagebox.showinfo("成功", f"日志已保存到: {filename}")
            except Exception as e:
                messagebox.showerror("错误", f"保存日志失败: {str(e)}")
    
    def _update_repo_progress(self, progress: int, status: str = ""):
        """更新仓库管理页面进度"""
        self.repo_progress_var.set(progress)
        self.repo_progress_label.config(text=f"{progress}%")
        if status:
            self.repo_status_var.set(status)
    
    def setup_toolbar(self, parent):
        """设置工具栏"""
        toolbar_container = ttk.Frame(parent)
        toolbar_container.pack(fill=X, pady=(0, 10))
        
        # 第一行：基本操作
        toolbar_row1 = ttk.Frame(toolbar_container)
        toolbar_row1.pack(fill=X, pady=(0, 5))
        
        # 刷新按钮
        self.refresh_btn = ttk_bs.Button(
            toolbar_row1,
            text="刷新列表",
            bootstyle=INFO,
            command=self.refresh_repositories,
            width=15
        )
        self.refresh_btn.pack(side=LEFT, padx=(0, 5))
        
        # 全选/取消全选
        self.select_all_btn = ttk_bs.Button(
            toolbar_row1,
            text="全选",
            bootstyle=SECONDARY,
            command=self.toggle_select_all,
            width=10
        )
        self.select_all_btn.pack(side=LEFT, padx=5)
        
        # 清除选择按钮
        clear_selection_btn = ttk_bs.Button(
            toolbar_row1,
            text="清除选择",
            bootstyle=LIGHT,
            command=self.clear_selection,
            width=10
        )
        clear_selection_btn.pack(side=LEFT, padx=5)
        
        # 选择状态标签
        self.selection_label = ttk.Label(toolbar_row1, text="已选择: 0 个")
        self.selection_label.pack(side=LEFT, padx=10)
        
        # 过滤选项
        filter_frame = ttk.Frame(toolbar_row1)
        filter_frame.pack(side=RIGHT)
        
        ttk.Label(filter_frame, text="过滤:").pack(side=LEFT, padx=(10, 5))
        
        self.filter_var = tk.StringVar(value="全部")
        filter_combo = ttk_bs.Combobox(
            filter_frame,
            textvariable=self.filter_var,
            values=["全部", "公开", "私有"],
            width=10,
            state="readonly"
        )
        filter_combo.pack(side=LEFT)
        filter_combo.bind("<<ComboboxSelected>>", self.apply_filter)
        
        # 搜索框
        search_frame = ttk.Frame(toolbar_row1)
        search_frame.pack(side=RIGHT, padx=(0, 10))
        
        ttk.Label(search_frame, text="搜索:").pack(side=LEFT)
        self.search_var = tk.StringVar()
        search_entry = ttk.Entry(search_frame, textvariable=self.search_var, width=20)
        search_entry.pack(side=LEFT, padx=5)
        search_entry.bind('<KeyRelease>', self.apply_search)
        
        # 第二行：批量操作按钮
        toolbar_row2 = ttk.Frame(toolbar_container)
        toolbar_row2.pack(fill=X)
        
        # 批量操作按钮
        ttk_bs.Button(
            toolbar_row2,
            text="批量设为公开",
            bootstyle=SUCCESS,
            command=lambda: self.batch_change_visibility(False),
            width=15
        ).pack(side=LEFT, padx=(0, 5))
        
        ttk_bs.Button(
            toolbar_row2,
            text="批量设为私有",
            bootstyle=WARNING,
            command=lambda: self.batch_change_visibility(True),
            width=15
        ).pack(side=LEFT, padx=5)
        
        ttk_bs.Button(
            toolbar_row2,
            text="批量删除",
            bootstyle=DANGER,
            command=self.batch_delete_repos,
            width=15
        ).pack(side=LEFT, padx=5)
        
        ttk_bs.Button(
            toolbar_row2,
            text="批量生成AI描述",
            bootstyle=INFO,
            command=self.batch_generate_descriptions,
            width=18
        ).pack(side=LEFT, padx=5)
        
        ttk_bs.Button(
            toolbar_row2,
            text="批量AI生成README",
            bootstyle=SUCCESS,
            command=self.batch_generate_readme,
            width=20
        ).pack(side=LEFT, padx=5)
        
        # 配置提示
        config_hint = ttk.Label(
            toolbar_row2, 
            text="💡 批量操作配置请在【配置设置】页面设置",
            font=("等线", 8),
            foreground="gray"
        )
        config_hint.pack(side=RIGHT, padx=10)
    
    def setup_repo_list(self, parent):
        """设置仓库列表"""
        list_frame = ttk_bs.LabelFrame(parent, text="仓库列表", padding=10)
        list_frame.pack(fill=BOTH, expand=True, pady=(0, 10))
        
        # 创建Treeview
        columns = ('select', 'name', 'visibility', 'description', 'updated', 'size')
        self.tree = ttk.Treeview(list_frame, columns=columns, show='headings', height=15)
        
        # 设置列标题和宽度
        self.tree.heading('select', text='选择')
        self.tree.heading('name', text='仓库名称')
        self.tree.heading('visibility', text='可见性')
        self.tree.heading('description', text='描述')
        self.tree.heading('updated', text='更新时间')
        self.tree.heading('size', text='大小')
        
        self.tree.column('select', width=60, anchor='center')
        self.tree.column('name', width=200)
        self.tree.column('visibility', width=80, anchor='center')
        self.tree.column('description', width=300)
        self.tree.column('updated', width=120)
        self.tree.column('size', width=80, anchor='center')
        
        # 滚动条
        scrollbar = ttk.Scrollbar(list_frame, orient=VERTICAL, command=self.tree.yview)
        self.tree.configure(yscrollcommand=scrollbar.set)
        
        # 绑定事件
        self.tree.bind('<Button-1>', self.on_tree_click)
        self.tree.bind('<Double-1>', self.on_repo_double_click)
        
        # 布局
        self.tree.pack(side=LEFT, fill=BOTH, expand=True)
        scrollbar.pack(side=RIGHT, fill=Y)
        
        # 右键菜单
        self.setup_context_menu()
    
    def setup_context_menu(self):
        """设置右键菜单"""
        self.context_menu = tk.Menu(self, tearoff=0)
        self.context_menu.add_command(label="查看详情", command=self.view_repo_details)
        self.context_menu.add_separator()
        self.context_menu.add_command(label="设置为公开", command=lambda: self.change_repo_visibility(False))
        self.context_menu.add_command(label="设置为私有", command=lambda: self.change_repo_visibility(True))
        self.context_menu.add_separator()
        self.context_menu.add_command(label="生成AI描述", command=self.generate_ai_description)
        self.context_menu.add_command(label="编辑描述", command=self.edit_repo_description)
        self.context_menu.add_separator()
        self.context_menu.add_command(label="删除仓库", command=self.delete_selected_repo)
        
        # 绑定右键菜单
        self.tree.bind('<Button-3>', self.show_context_menu)
    
    # setup_action_panel方法已删除，批量操作按钮已移动到工具栏
    def set_gitee_manager(self, manager: GiteeManager):
        """设置Gitee管理器"""
        self.gitee_manager = manager
        self.logger.info("Gitee管理器已设置")
    
    def refresh_repositories(self):
        """刷新仓库列表"""
        if not self.gitee_manager:
            messagebox.showerror("错误", "请先配置Gitee连接")
            return
        
        # 禁用刷新按钮
        self.refresh_btn.configure(state=DISABLED, text="刷新中...")
        
        # 在后台线程中获取仓库列表
        threading.Thread(target=self._fetch_repositories, daemon=True).start()
    
    def _fetch_repositories(self):
        """后台获取仓库列表"""
        try:
            success, repos, message = self.gitee_manager.get_all_repositories()
            
            if success:
                self.repositories = repos
                # 在主线程中更新UI
                self.after(0, self._update_repo_list)
                self.after(0, lambda: messagebox.showinfo("成功", message))
            else:
                self.after(0, lambda: messagebox.showerror("错误", f"获取仓库列表失败: {message}"))
                
        except Exception as e:
            error_msg = f"获取仓库列表异常: {str(e)}"
            self.logger.error(error_msg)
            self.after(0, lambda: messagebox.showerror("错误", error_msg))
        finally:
            # 恢复刷新按钮
            self.after(0, lambda: self.refresh_btn.configure(state=NORMAL, text="刷新列表"))
    
    def _update_repo_list(self):
        """更新仓库列表显示"""
        # 清空现有数据
        for item in self.tree.get_children():
            self.tree.delete(item)
        
        # 使用过滤功能显示数据
        self._update_filtered_repos()
        
        # 更新选择状态显示
        self._update_selection_count()
    
    def on_tree_click(self, event):
        """处理列表点击事件"""
        # 获取点击的行
        item = self.tree.identify_row(event.y)
        if not item:
            return
        
        # 获取点击的列
        column = self.tree.identify_column(event.x)
        
        # 如果点击的是选择列（第一列）
        if column == '#1':
            self.toggle_repo_selection(item)
        else:
            # 点击其他列时选中该行（但不切换勾选状态）
            self.tree.selection_set(item)
    
    def toggle_repo_selection(self, item):
        """切换仓库选择状态"""
        values = list(self.tree.item(item, 'values'))
        repo_name = values[1]
        
        if values[0] == '☐':  # 未选择
            values[0] = '☑'  # 选中
            if repo_name not in self.selected_repos:
                self.selected_repos.append(repo_name)
        else:  # 已选择
            values[0] = '☐'  # 取消选择
            if repo_name in self.selected_repos:
                self.selected_repos.remove(repo_name)
        
        self.tree.item(item, values=values)
        
        # 更新全选按钮状态
        self._update_selection_count()
        
        self.logger.info(f"切换仓库选择: {repo_name}, 当前选中: {len(self.selected_repos)} 个")
    
    def _update_selection_count(self):
        """更新选择计数和按钮状态"""
        selected_count = len(self.selected_repos)
        total_count = len(self.repositories)
        
        # 更新选择状态标签
        self.selection_label.configure(text=f"已选择: {selected_count} 个")
        
        # 更新全选按钮状态
        if selected_count == 0:
            self.select_all_btn.configure(text="全选")
        elif selected_count == total_count:
            self.select_all_btn.configure(text="取消全选")
        else:
            self.select_all_btn.configure(text=f"全选({selected_count}/{total_count})")
    
    def toggle_select_all(self):
        """全选/取消全选"""
        if len(self.selected_repos) == len(self.repositories):
            # 当前全选，取消全选
            self.selected_repos.clear()
            self.select_all_btn.configure(text="全选")
            select_symbol = '☐'
        else:
            # 全选
            self.selected_repos.clear()
            for repo in self.repositories:
                # 使用与显示一致的仓库标识符（包含用户名的完整路径）
                repo_identifier = repo.get('full_name', repo.get('name', ''))
                # 如果没有full_name，则用所有者/路径组合
                if not repo_identifier or '/' not in repo_identifier:
                    owner_login = repo.get('owner', {}).get('login', '')
                    repo_path = repo.get('path', repo.get('name', ''))
                    if owner_login and repo_path:
                        repo_identifier = f"{owner_login}/{repo_path}"
                
                if repo_identifier and repo_identifier not in self.selected_repos:
                    self.selected_repos.append(repo_identifier)
            
            self.select_all_btn.configure(text="取消全选")
            select_symbol = '☑'
        
        # 更新显示
        for item in self.tree.get_children():
            values = list(self.tree.item(item, 'values'))
            values[0] = select_symbol
            self.tree.item(item, values=values)
        
        # 更新选中状态显示
        self._update_selection_count()
        
        self.logger.info(f"全选操作: {select_symbol == '☑'}, 当前选中: {len(self.selected_repos)} 个")
    
    def clear_selection(self):
        """清除所有选择"""
        self.selected_repos.clear()
        
        # 更新显示
        for item in self.tree.get_children():
            values = list(self.tree.item(item, 'values'))
            values[0] = '☐'
            self.tree.item(item, values=values)
        
        # 更新选择计数
        self._update_selection_count()
        
        self.logger.info("已清除所有选择")
    
    def apply_filter(self, event=None):
        """应用过滤器"""
        self._update_filtered_repos()
    
    def apply_search(self, event=None):
        """应用搜索"""
        self._update_filtered_repos()
    
    def _update_filtered_repos(self):
        """根据搜索和过滤条件更新显示"""
        if not self.repositories:
            return
        
        # 清空现有数据
        for item in self.tree.get_children():
            self.tree.delete(item)
        
        # 获取筛选条件
        filter_value = self.filter_var.get()
        search_term = self.search_var.get().lower()
        
        filtered_repos = []
        for repo in self.repositories:
            # 应用可见性筛选
            repo_private = repo.get('private', True)
            if filter_value == "公开" and repo_private:
                continue
            elif filter_value == "私有" and not repo_private:
                continue
            
            # 应用搜索筛选
            if search_term:
                repo_name = repo.get('name', '').lower()
                repo_desc = repo.get('description', '').lower()
                repo_full_name = repo.get('full_name', '').lower()
                
                if (search_term not in repo_name and 
                    search_term not in repo_desc and 
                    search_term not in repo_full_name):
                    continue
            
            filtered_repos.append(repo)
        
        # 显示过滤后的仓库
        for repo in filtered_repos:
            visibility = "私有" if repo.get('private', True) else "公开"
            description = repo.get('description', '') or '无描述'
            updated_at = repo.get('updated_at', '')[:10] if repo.get('updated_at') else ''
            size = f"{repo.get('size', 0)}KB"
            
            # 使用完整名称（包含用户名）确保唯一性和正确性
            repo_identifier = repo.get('full_name', repo.get('name', ''))
            # 如果没有full_name，则用所有者/路径组合
            if not repo_identifier or '/' not in repo_identifier:
                owner_login = repo.get('owner', {}).get('login', '')
                repo_path = repo.get('path', repo.get('name', ''))
                if owner_login and repo_path:
                    repo_identifier = f"{owner_login}/{repo_path}"
            
            self.tree.insert('', END, values=(
                '☐',  # 未选择
                repo_identifier,  # 使用完整名称作为标识符
                visibility,
                description,
                updated_at,
                size
            ))
        
        self.logger.info(f"过滤后显示 {len(filtered_repos)} 个仓库（总共 {len(self.repositories)} 个）")
    
    def show_context_menu(self, event):
        """显示右键菜单"""
        item = self.tree.identify_row(event.y)
        if item:
            self.tree.selection_set(item)
            self.context_menu.post(event.x_root, event.y_root)
    
    def get_selected_repo_name(self) -> Optional[str]:
        """获取当前选中的仓库名称"""
        selection = self.tree.selection()
        if selection:
            values = self.tree.item(selection[0], 'values')
            return values[1]
        return None
    
    def batch_change_visibility(self, is_private: bool):
        """批量修改可见性"""
        if not self.selected_repos:
            messagebox.showwarning("警告", "请先选择要操作的仓库")
            return
        
        if not self.gitee_manager:
            messagebox.showerror("错误", "Gitee连接未配置")
            return
        
        visibility_text = "私有" if is_private else "公开"
        if not messagebox.askyesno("确认", f"确定要将选中的 {len(self.selected_repos)} 个仓库设置为{visibility_text}吗？"):
            return
        
        # 在后台线程中执行
        threading.Thread(
            target=self._batch_change_visibility_worker,
            args=(is_private,),
            daemon=True
        ).start()
    
    def _batch_change_visibility_worker(self, is_private: bool):
        """批量修改可见性工作线程"""
        try:
            visibility_text = "私有" if is_private else "公开"
            progress_widget = self.progress_manager.start_batch_operation(
                f"批量设为{visibility_text}", len(self.selected_repos)
            )
            
            success_count = 0
            fail_count = 0
            
            for i, repo_name in enumerate(self.selected_repos, 1):
                if self.progress_manager.is_cancelled:
                    break
                
                self.progress_manager.update_item(i, repo_name, f"设为{visibility_text}")
                
                success, message = self.gitee_manager.update_repository_visibility(repo_name, is_private)
                if success:
                    success_count += 1
                else:
                    fail_count += 1
                    self.logger.error(f"修改 {repo_name} 失败: {message}")
            
            self.progress_manager.complete_operation(success_count, fail_count)
            
            if not self.progress_manager.is_cancelled:
                self.after(0, self.refresh_repositories)
            
        except Exception as e:
            error_msg = f"批量修改异常: {str(e)}"
            self.logger.error(error_msg)
            if hasattr(self, 'progress_manager') and self.progress_manager.progress_widget:
                self.progress_manager.progress_widget.set_status(f"操作失败: {error_msg}")
            self.after(0, lambda: messagebox.showerror("错误", error_msg))
    
    def batch_delete_repos(self):
        """批量删除仓库"""
        if not self.selected_repos:
            messagebox.showwarning("警告", "请先选择要删除的仓库")
            return
        
        if not self.gitee_manager:
            messagebox.showerror("错误", "Gitee连接未配置")
            return
        
        if not messagebox.askyesno("危险操作", 
                                  f"确定要删除选中的 {len(self.selected_repos)} 个仓库吗？\n\n"
                                  f"此操作不可恢复！\n\n"
                                  f"将删除: {', '.join(self.selected_repos[:5])}"
                                  f"{'...' if len(self.selected_repos) > 5 else ''}"):
            return
        
        # 在后台线程中执行
        threading.Thread(target=self._batch_delete_worker, daemon=True).start()
    
    def _batch_delete_worker(self):
        """批量删除工作线程"""
        try:
            progress_widget = self.progress_manager.start_batch_operation(
                "批量删除仓库", len(self.selected_repos)
            )
            
            success_count = 0
            fail_count = 0
            
            for i, repo_name in enumerate(self.selected_repos, 1):
                if self.progress_manager.is_cancelled:
                    break
                
                self.progress_manager.update_item(i, repo_name, "删除中")
                
                success, message = self.gitee_manager.delete_repository(repo_name)
                if success:
                    success_count += 1
                else:
                    fail_count += 1
                    self.logger.error(f"删除 {repo_name} 失败: {message}")
            
            self.progress_manager.complete_operation(success_count, fail_count)
            
            if not self.progress_manager.is_cancelled:
                self.after(0, self.refresh_repositories)
            
        except Exception as e:
            error_msg = f"批量删除异常: {str(e)}"
            self.logger.error(error_msg)
            if hasattr(self, 'progress_manager') and self.progress_manager.progress_widget:
                self.progress_manager.progress_widget.set_status(f"操作失败: {error_msg}")
            self.after(0, lambda: messagebox.showerror("错误", error_msg))
    
    def batch_generate_descriptions(self):
        """批量生成AI描述"""
        if not self.selected_repos:
            messagebox.showwarning("警告", "请先选择要生成描述的仓库")
            return
        
        # 在后台线程中执行
        threading.Thread(target=self._batch_generate_descriptions_worker, daemon=True).start()
    
    def _batch_generate_descriptions_worker(self):
        """批量生成描述工作线程"""
        try:
            progress_widget = self.progress_manager.start_batch_operation(
                "批量生成AI描述", len(self.selected_repos)
            )
            
            success_count = 0
            fail_count = 0
            
            for i, repo_name in enumerate(self.selected_repos, 1):
                if self.progress_manager.is_cancelled:
                    break
                
                self.progress_manager.update_item(i, repo_name, "生成AI描述")
                
                # 生成描述
                description = deepseek_ai.generate_description(repo_name, "")
                
                # 更新到Gitee
                if self.gitee_manager:
                    success, message = self.gitee_manager.update_repository_description(repo_name, description)
                    if success:
                        success_count += 1
                    else:
                        fail_count += 1
                        self.logger.error(f"更新 {repo_name} 描述失败: {message}")
            
            self.progress_manager.complete_operation(success_count, fail_count)
            
            if not self.progress_manager.is_cancelled:
                self.after(0, self.refresh_repositories)
            
        except Exception as e:
            error_msg = f"批量生成描述异常: {str(e)}"
            self.logger.error(error_msg)
            if hasattr(self, 'progress_manager') and self.progress_manager.progress_widget:
                self.progress_manager.progress_widget.set_status(f"操作失败: {error_msg}")
            self.after(0, lambda: messagebox.showerror("错误", error_msg))
    
    
    
    def on_repo_double_click(self, event):
        """双击仓库事件"""
        self.view_repo_details()
    
    def view_repo_details(self):
        """查看仓库详情"""
        repo_name = self.get_selected_repo_name()
        if repo_name:
            # 找到对应的仓库数据
            repo_data = next((repo for repo in self.repositories if repo.get('name') == repo_name), None)
            if repo_data:
                self._show_repo_details_dialog(repo_data)
    
    def _show_repo_details_dialog(self, repo_data: Dict):
        """显示仓库详情对话框"""
        dialog = tk.Toplevel(self)
        dialog.title(f"仓库详情 - {repo_data.get('name', '')}")
        dialog.geometry("600x400")
        dialog.grab_set()
        
        # 创建详情文本
        details_text = tk.Text(dialog, wrap=tk.WORD, padx=10, pady=10)
        details_text.pack(fill=BOTH, expand=True, padx=10, pady=10)
        
        # 填充详情信息
        details = f"""仓库名称: {repo_data.get('name', '')}
描述: {repo_data.get('description', '') or '无描述'}
可见性: {'私有' if repo_data.get('private', True) else '公开'}
语言: {repo_data.get('language', '') or '未知'}
大小: {repo_data.get('size', 0)}KB
星标数: {repo_data.get('stargazers_count', 0)}
派生数: {repo_data.get('forks_count', 0)}
创建时间: {repo_data.get('created_at', '')[:19] if repo_data.get('created_at') else ''}
更新时间: {repo_data.get('updated_at', '')[:19] if repo_data.get('updated_at') else ''}
克隆URL: {repo_data.get('clone_url', '')}
SSH URL: {repo_data.get('ssh_url', '')}
网页URL: {repo_data.get('html_url', '')}
"""
        
        details_text.insert(tk.END, details)
        details_text.configure(state=tk.DISABLED)
        
        # 关闭按钮
        ttk_bs.Button(
            dialog,
            text="关闭",
            command=dialog.destroy,
            width=15
        ).pack(pady=10)
        
        dialog.transient(self)
    
    def change_repo_visibility(self, is_private: bool):
        """修改单个仓库可见性"""
        repo_name = self.get_selected_repo_name()
        if not repo_name:
            return
        
        if not self.gitee_manager:
            messagebox.showerror("错误", "Gitee连接未配置")
            return
        
        # 在后台线程中执行
        threading.Thread(
            target=self._change_repo_visibility_worker,
            args=(repo_name, is_private),
            daemon=True
        ).start()
    
    def _change_repo_visibility_worker(self, repo_name: str, is_private: bool):
        """修改仓库可见性工作线程"""
        try:
            success, message = self.gitee_manager.update_repository_visibility(repo_name, is_private)
            
            if success:
                self.after(0, lambda: messagebox.showinfo("成功", message))
                self.after(0, self.refresh_repositories)
            else:
                self.after(0, lambda: messagebox.showerror("失败", message))
                
        except Exception as e:
            error_msg = f"修改仓库可见性异常: {str(e)}"
            self.logger.error(error_msg)
            self.after(0, lambda: messagebox.showerror("错误", error_msg))
    
    def generate_ai_description(self):
        """为单个仓库生成AI描述"""
        repo_name = self.get_selected_repo_name()
        if not repo_name:
            return
        
        # 在后台线程中执行
        threading.Thread(
            target=self._generate_ai_description_worker,
            args=(repo_name,),
            daemon=True
        ).start()
    
    def _generate_ai_description_worker(self, repo_name: str):
        """生成AI描述工作线程"""
        try:
            # 生成描述（这里简化处理，项目路径留空）
            description = deepseek_ai.generate_description(repo_name, "")
            
            # 更新到Gitee
            if self.gitee_manager:
                success, message = self.gitee_manager.update_repository_description(repo_name, description)
                
                if success:
                    self.after(0, lambda: messagebox.showinfo("成功", f"AI描述生成并更新成功！\n\n描述: {description}"))
                    self.after(0, self.refresh_repositories)
                else:
                    self.after(0, lambda: messagebox.showerror("失败", message))
                    
        except Exception as e:
            error_msg = f"生成AI描述异常: {str(e)}"
            self.logger.error(error_msg)
            self.after(0, lambda: messagebox.showerror("错误", error_msg))
    
    def edit_repo_description(self):
        """编辑仓库描述"""
        repo_name = self.get_selected_repo_name()
        if not repo_name:
            return
        
        # 找到当前描述
        current_desc = ""
        for repo in self.repositories:
            if repo.get('name') == repo_name:
                current_desc = repo.get('description', '')
                break
        
        # 创建编辑对话框
        dialog = tk.Toplevel(self)
        dialog.title(f"编辑描述 - {repo_name}")
        dialog.geometry("500x300")
        dialog.grab_set()
        
        # 描述输入框
        ttk.Label(dialog, text="仓库描述:").pack(pady=(10, 5))
        desc_text = tk.Text(dialog, height=10, wrap=tk.WORD)
        desc_text.pack(fill=BOTH, expand=True, padx=10, pady=5)
        desc_text.insert("1.0", current_desc)
        
        # 按钮
        button_frame = ttk.Frame(dialog)
        button_frame.pack(pady=10)
        
        def save_description():
            new_desc = desc_text.get("1.0", tk.END).strip()
            dialog.destroy()
            
            # 在后台更新
            threading.Thread(
                target=self._update_repo_description_worker,
                args=(repo_name, new_desc),
                daemon=True
            ).start()
        
        ttk_bs.Button(
            button_frame,
            text="保存",
            bootstyle=SUCCESS,
            command=save_description,
            width=15
        ).pack(side=LEFT, padx=5)
        
        ttk_bs.Button(
            button_frame,
            text="取消",
            bootstyle=SECONDARY,
            command=dialog.destroy,
            width=15
        ).pack(side=LEFT, padx=5)
        
        dialog.transient(self)
    
    def _update_repo_description_worker(self, repo_name: str, description: str):
        """更新仓库描述工作线程"""
        try:
            if self.gitee_manager:
                success, message = self.gitee_manager.update_repository_description(repo_name, description)
                
                if success:
                    self.after(0, lambda: messagebox.showinfo("成功", message))
                    self.after(0, self.refresh_repositories)
                else:
                    self.after(0, lambda: messagebox.showerror("失败", message))
                    
        except Exception as e:
            error_msg = f"更新仓库描述异常: {str(e)}"
            self.logger.error(error_msg)
            self.after(0, lambda: messagebox.showerror("错误", error_msg))
    
    def delete_selected_repo(self):
        """删除选中的仓库"""
        repo_name = self.get_selected_repo_name()
        if not repo_name:
            return
        
        if not messagebox.askyesno("危险操作", f"确定要删除仓库 '{repo_name}' 吗？\n\n此操作不可恢复！"):
            return
        
        # 在后台线程中执行
        threading.Thread(
            target=self._delete_repo_worker,
            args=(repo_name,),
            daemon=True
        ).start()
    
    def _delete_repo_worker(self, repo_name: str):
        """删除仓库工作线程"""
        try:
            if self.gitee_manager:
                success, message = self.gitee_manager.delete_repository(repo_name)
                
                if success:
                    self.after(0, lambda: messagebox.showinfo("成功", message))
                    self.after(0, self.refresh_repositories)
                else:
                    self.after(0, lambda: messagebox.showerror("失败", message))
                    
        except Exception as e:
            error_msg = f"删除仓库异常: {str(e)}"
            self.logger.error(error_msg)
            self.after(0, lambda: messagebox.showerror("错误", error_msg))
    
    def batch_generate_readme(self):
        """批量AI生成README"""
        if not self.selected_repos:
            messagebox.showwarning("警告", "请先选择要处理的仓库")
            return
        
        if not self.gitee_manager:
            messagebox.showerror("错误", "请先配置Gitee连接")
            return
        
        # 确认对话框
        count = len(self.selected_repos)
        if not messagebox.askyesno("确认操作", f"将为 {count} 个仓库批量AI重新生成README文件\n\n此操作将：\n1. 调用DeepSeek AI重新生成README内容\n2. 完全替换现有README内容\n3. 通过API直接更新到仓库\n4. 不占用本地硬盘空间\n5. 基于仓库信息智能分析生成\n\n⚠️ 注意：现有README内容将被AI生成的内容完全替换！\n\n确定继续吗？"):
            return
        
        # 在后台线程中执行批量操作
        threading.Thread(
            target=self._batch_generate_readme_worker,
            daemon=True
        ).start()
    
    def _batch_generate_readme_worker(self):
        """批量生成README工作线程"""
        try:
            total_count = len(self.selected_repos)
            success_count = 0
            failed_repos = []
            
            # 初始化进度和日志
            self.after(0, lambda: self._update_repo_progress(0, "开始批量AI生成README..."))
            self.after(0, lambda: self._append_repo_log(f"开始批量AI生成README，共 {total_count} 个仓库", "INFO"))
            
            for i, repo_name in enumerate(self.selected_repos):
                try:
                    # 更新进度
                    progress = int((i / total_count) * 100)
                    self.after(0, lambda p=progress, rn=repo_name, idx=i+1: self._update_repo_progress(
                        p, f"正在处理: {rn} ({idx}/{total_count})"
                    ))
                    self.after(0, lambda rn=repo_name, idx=i+1: self._append_repo_log(
                        f"正在处理: {rn} ({idx}/{total_count})", "INFO"
                    ))
                    
                    # 获取仓库信息
                    repo_info = self._get_repo_info_by_name(repo_name)
                    if not repo_info:
                        failed_repos.append(f"{repo_name} (未找到仓库信息)")
                        self.after(0, lambda rn=repo_name: self._append_repo_log(f"✗ {rn} 未找到仓库信息", "ERROR"))
                        continue
                    
                    # 生成README内容
                    self.after(0, lambda rn=repo_name: self._append_repo_log(f"正在为 {rn} 生成AI内容...", "INFO"))
                    readme_content = self._generate_readme_for_repo(repo_info)
                    if not readme_content:
                        failed_repos.append(f"{repo_name} (生成内容失败)")
                        self.after(0, lambda rn=repo_name: self._append_repo_log(f"✗ {rn} 生成内容失败", "ERROR"))
                        continue
                    
                    # 通过API更新README
                    repo_full_name = repo_info.get('full_name', '')
                    if not repo_full_name:
                        failed_repos.append(f"{repo_name} (无法获取完整名称)")
                        self.after(0, lambda rn=repo_name: self._append_repo_log(f"✗ {rn} 无法获取完整名称", "ERROR"))
                        continue
                    
                    self.after(0, lambda rn=repo_name: self._append_repo_log(f"正在更新 {rn} 的README...", "INFO"))
                    success, message = self.gitee_manager.gitee_api.update_file_content(
                        repo_full_name, 
                        "README.md", 
                        readme_content, 
                        "AI自动生成README文件",
                        "master"
                    )
                    
                    if success:
                        success_count += 1
                        self.after(0, lambda rn=repo_name: self._append_repo_log(f"✓ {rn} README更新成功", "SUCCESS"))
                    else:
                        failed_repos.append(f"{repo_name} (API更新失败: {message})")
                        self.after(0, lambda rn=repo_name, msg=message: self._append_repo_log(f"✗ {rn} README更新失败: {msg}", "ERROR"))
                        
                except Exception as e:
                    error_msg = f"处理仓库 {repo_name} 时出错: {str(e)}"
                    self.logger.error(error_msg)
                    failed_repos.append(f"{repo_name} (处理异常: {str(e)})")
                    self.after(0, lambda rn=repo_name, err=str(e): self._append_repo_log(f"✗ {rn} 处理异常: {err}", "ERROR"))
            
            # 完成操作
            self.after(0, lambda: self._update_repo_progress(100, "批量操作完成"))
            self.after(0, lambda: self._append_repo_log(f"批量操作完成！成功: {success_count} 个，失败: {len(failed_repos)} 个", "SUCCESS"))
            
            # 显示结果
            if success_count > 0:
                success_msg = f"批量生成README完成！\n\n成功: {success_count} 个\n失败: {len(failed_repos)} 个"
                if failed_repos:
                    success_msg += f"\n\n失败的仓库:\n" + "\n".join(failed_repos[:10])
                    if len(failed_repos) > 10:
                        success_msg += f"\n... 还有 {len(failed_repos) - 10} 个"
                
                self.after(0, lambda: messagebox.showinfo("批量操作完成", success_msg))
            else:
                self.after(0, lambda: messagebox.showerror("批量操作失败", 
                    f"所有仓库都处理失败！\n\n失败的仓库:\n" + "\n".join(failed_repos[:10])))
                
        except Exception as e:
            error_msg = f"批量生成README异常: {str(e)}"
            self.logger.error(error_msg)
            self.after(0, lambda: messagebox.showerror("错误", error_msg))
        finally:
            self.after(0, lambda: self.progress_manager.complete_batch_operation())
    
    def _get_repo_info_by_name(self, repo_name: str) -> Optional[Dict]:
        """根据仓库名称获取仓库信息"""
        # 如果repo_name包含用户名前缀，提取仓库名
        if '/' in repo_name:
            actual_repo_name = repo_name.split('/')[-1]
        else:
            actual_repo_name = repo_name
        
        # 首先尝试完整匹配
        for repo in self.repositories:
            if repo.get('name') == repo_name or repo.get('full_name') == repo_name:
                return repo
        
        # 然后尝试只匹配仓库名
        for repo in self.repositories:
            if repo.get('name') == actual_repo_name:
                return repo
                
        return None
    
    def _generate_readme_for_repo(self, repo_info: Dict) -> Optional[str]:
        """为仓库重新生成README内容（调用DeepSeek AI）"""
        try:
            from utils.readme_generator import ReadmeGenerator
            
            # 准备项目信息
            project_info = {
                'name': repo_info.get('name', ''),
                'description': repo_info.get('description', ''),
                'author': '开发者'
            }
            
            # 创建README生成器
            readme_gen = ReadmeGenerator()
            
            # 获取仓库完整名称用于AI分析
            repo_full_name = repo_info.get('full_name', '')
            
            # 首先尝试调用DeepSeek AI生成
            readme_content = readme_gen.generate_ai_readme(repo_full_name, project_info)
            
            if readme_content:
                self.logger.info(f"DeepSeek AI成功为仓库 {repo_info.get('name')} 生成README")
                return readme_content
            
            # 如果AI生成失败，使用智能本地分析
            self.logger.warning(f"DeepSeek AI生成失败，使用本地智能分析为仓库 {repo_info.get('name')}")
            
            # 根据仓库语言和技术栈生成更准确的内容
            language = repo_info.get('language', '')
            project_type = self._detect_project_type(language, repo_info.get('name', ''))
            technologies = self._detect_technologies(language, repo_info.get('name', ''))
            
            # 使用本地智能分析生成README内容
            readme_content = readme_gen._generate_local_ai_readme(project_info, {
                'project_type': project_type,
                'main_technologies': technologies,
                'description': project_info['description'] or f'一个优秀的{project_type}项目',
                'features': self._generate_features(project_type, technologies),
                'installation': self._generate_installation_guide(technologies),
                'usage': self._generate_usage_guide(project_type),
                'language': language
            })
            
            return readme_content
            
        except Exception as e:
            self.logger.error(f"重新生成README内容失败: {str(e)}")
            return None
    
    def _detect_project_type(self, language: str, repo_name: str) -> str:
        """检测项目类型"""
        name_lower = repo_name.lower()
        
        if 'web' in name_lower or 'frontend' in name_lower or 'ui' in name_lower:
            return 'Web前端应用'
        elif 'backend' in name_lower or 'api' in name_lower or 'server' in name_lower:
            return '后端服务'
        elif 'mobile' in name_lower or 'app' in name_lower:
            return '移动应用'
        elif 'desktop' in name_lower or 'client' in name_lower:
            return '桌面应用'
        elif language == 'Python':
            return 'Python项目'
        elif language == 'JavaScript':
            return 'JavaScript项目'
        elif language == 'Java':
            return 'Java项目'
        elif language == 'C++':
            return 'C++项目'
        else:
            return '软件开发项目'
    
    def _detect_technologies(self, language: str, repo_name: str) -> List[str]:
        """检测技术栈"""
        technologies = []
        name_lower = repo_name.lower()
        
        # 根据语言添加基础技术
        if language:
            technologies.append(language)
        
        # 根据仓库名称推测技术栈
        if 'react' in name_lower:
            technologies.extend(['React', 'JavaScript', 'HTML', 'CSS'])
        elif 'vue' in name_lower:
            technologies.extend(['Vue.js', 'JavaScript', 'HTML', 'CSS'])
        elif 'angular' in name_lower:
            technologies.extend(['Angular', 'TypeScript', 'HTML', 'CSS'])
        elif 'spring' in name_lower:
            technologies.extend(['Spring Boot', 'Java', 'Maven'])
        elif 'django' in name_lower:
            technologies.extend(['Django', 'Python', 'SQLite'])
        elif 'flask' in name_lower:
            technologies.extend(['Flask', 'Python', 'SQLite'])
        elif 'express' in name_lower:
            technologies.extend(['Express.js', 'Node.js', 'JavaScript'])
        elif 'laravel' in name_lower:
            technologies.extend(['Laravel', 'PHP', 'MySQL'])
        else:
            # 默认技术栈
            if language == 'Python':
                technologies.extend(['Python', 'pip'])
            elif language == 'JavaScript':
                technologies.extend(['JavaScript', 'npm'])
            elif language == 'Java':
                technologies.extend(['Java', 'Maven'])
            else:
                technologies.extend(['HTML', 'CSS', 'JavaScript'])
        
        return list(set(technologies))  # 去重
    
    def _generate_features(self, project_type: str, technologies: List[str]) -> List[str]:
        """生成功能特性"""
        features = []
        
        if 'Web' in project_type:
            features.extend(['响应式设计', '现代化界面', '用户友好'])
        elif '后端' in project_type:
            features.extend(['高性能', '可扩展', '安全可靠'])
        elif '移动' in project_type:
            features.extend(['跨平台', '原生性能', '流畅体验'])
        
        if 'React' in technologies or 'Vue' in technologies:
            features.append('组件化开发')
        if 'Spring' in technologies:
            features.append('企业级架构')
        if 'Django' in technologies or 'Flask' in technologies:
            features.append('快速开发')
        
        return features[:5]  # 最多5个特性
    
    def _generate_installation_guide(self, technologies: List[str]) -> str:
        """生成安装指南"""
        if 'Python' in technologies:
            return '```bash\npip install -r requirements.txt\npython main.py\n```'
        elif 'JavaScript' in technologies and 'npm' in technologies:
            return '```bash\nnpm install\nnpm start\n```'
        elif 'Java' in technologies and 'Maven' in technologies:
            return '```bash\nmvn clean install\nmvn spring-boot:run\n```'
        else:
            return '请参考项目文档进行安装和配置'
    
    def _generate_usage_guide(self, project_type: str) -> str:
        """生成使用指南"""
        if 'Web' in project_type:
            return '1. 启动项目\n2. 在浏览器中访问相应地址\n3. 按照界面提示进行操作'
        elif '后端' in project_type:
            return '1. 配置数据库连接\n2. 启动服务\n3. 通过API接口调用功能'
        elif '移动' in project_type:
            return '1. 安装应用\n2. 注册/登录账号\n3. 开始使用各项功能'
        else:
            return '请参考项目文档了解详细使用方法'
